package com.rq.base.ui;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.PopupWindow;
import android.widget.ScrollView;


import com.gyf.immersionbar.ImmersionBar;
import com.rq.base.BASE;
import com.rq.base.R;
import com.rq.base.net.impl.BaseBeanImpl;
import com.rq.base.net.RequestType;
import com.rq.base.ui.impl.BaseView;
import com.rq.base.ui.impl.CtrListener;
import com.rq.base.ui.impl.CtrTag;
import com.rq.base.ui.impl.OnClick;
import com.rq.base.ui.impl.OnRefuseAndLoadListener;
import com.rq.base.util.AppUtils;
import com.rq.base.util.LOG;
import com.rq.base.util.ToastUtil;
//import com.scwang.smart.refresh.footer.ClassicsFooter;
//import com.scwang.smart.refresh.header.ClassicsHeader;
//import com.scwang.smart.refresh.layout.SmartRefreshLayout;
//import com.scwang.smart.refresh.layout.api.RefreshLayout;
//import com.scwang.smart.refresh.layout.listener.OnLoadMoreListener;
//import com.scwang.smart.refresh.layout.listener.OnRefreshListener;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import androidx.annotation.ColorRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.rq.base.ui.BaseActivity.TAG_OPEN_CODE;

/**
 * 用  Controller 代替 Activity 和 Fragment 简化维护
 * 逻辑无关：与应用本身没有关系，任何应用可以复制的基类
 * 需要重写控件装填规则  实现 {@link FillMoreMethod} 即可
 * 需要增加点击事件 实现 View.OnClickListener ,并且以 {@link OnClick}写入控件id
 */
public abstract class BaseController implements BaseView {

    public boolean isTransparentActivity() {
        return false;
    }

    ViewDelegate mViewDelegate;

    public BaseController() {
        this.mViewDelegate = new ViewDelegate();
    }

    /**
     * 外部数据传输
     *
     * @param obj
     */
    public boolean onAction(Object obj) {
        return false;
    }

    public boolean dispatchKeyEvent(KeyEvent event) {
        return false;
    }

    public void onProgressCancel(DialogInterface dialog) {

    }

    public boolean onTouchEvent(MotionEvent event) {
        return false;
    }

    public void toast(int s) {
        ToastUtil.show(s);
    }

    public void toast(String s) {
        ToastUtil.show(s);
    }

    public static final String TAG_PASS = "controller.pass";
    public static final String TAG_PASS_DATA_SIZE = "this.size.of.pass";
    public static final String TAG_NAME = "controller";
    int refuseViewId = 0;
    List<BaseController> attachChild = new ArrayList<>();
    private int innerPassCode = 0;

    public <P extends BaseController> void skip(Class<P> clazz, Serializable... pass) {
        if (mOperator != null && mOperator.skip(this, clazz, pass)) {
            attachChild.remove(this);
            mOperator.finish(this);
            return;
        }
        BaseActivity.skip(this, clazz, pass);
    }

    protected final void showEmpty() {
        if (justLayout()) {
            ViewGroup viewGroup;
            if (mFragment != null) {
                viewGroup = (ViewGroup) mFragment.fraRoot;
            } else {
                viewGroup = (ViewGroup) (getActivity()).getRootView();
            }
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                viewGroup.getChildAt(i).setVisibility(View.GONE);
            }
            View empty = getActivity().getLayoutInflater().inflate(R.layout.layout_empty, null);
            empty.setTag("EMPTY");
            empty.findViewById(R.id.empty).setVisibility(View.VISIBLE);
            empty.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    emptyClick();
                }
            });
            viewGroup.addView(empty, new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
        } else {
            getView(R.id.base_container).setVisibility(View.GONE);
            getView(R.id.empty).setVisibility(View.VISIBLE);
        }
    }

    protected void emptyClick() {
    }

    protected final void hideEmpty() {
        if (justLayout()) {
            ViewGroup viewGroup;
            if (mFragment != null) {
                viewGroup = (ViewGroup) mFragment.fraRoot;
            } else {
                viewGroup = (ViewGroup) (getActivity()).getRootView();
            }
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                viewGroup.getChildAt(i).setVisibility(View.GONE);
            }
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                if ("EMPTY".equals(viewGroup.getChildAt(i).getTag())) {
                    viewGroup.getChildAt(i).setVisibility(View.GONE);
                } else {
                    viewGroup.getChildAt(i).setVisibility(View.VISIBLE);
                }
            }
        } else {
            getView(R.id.base_container).setVisibility(View.VISIBLE);
            getView(R.id.empty).setVisibility(View.GONE);
        }
    }


    /**
     * 普通的单业务数据专递
     * 建议使用 {@link #openWith(Class, int, Serializable...)} )}
     */
    @Deprecated
    public <P extends BaseController> void openFor(Class<P> clazz, Serializable... pass) {
        if (mOperator != null && mOperator.openFor(this, clazz, pass)) {
            LOG.d("BaseController", "openFor.222:" + clazz.getSimpleName());
            return;
        }
        BaseActivity.openFor(this, clazz, pass);
    }

    /**
     * 多业务数据传递
     *
     * @param requestCode 业务标识编码
     *                    可以直接在 onResultOk 使用 isBackFrom 方法判断
     *                    {@link #onResult(int, int, Intent)}}{@link #isBackWith(int, Intent)}
     * @see #getRequestCode()
     */
    public <P extends BaseController> void openWith(Class<P> clazz, int requestCode,
                                                    Serializable... pass) {
        BaseActivity.openWith(this, requestCode, clazz, pass);
    }

    public <P extends BaseController> void open(Class<P> clazz, Serializable... pass) {
        if (mOperator != null && mOperator.open(this, clazz, pass)) {
            LOG.d("BaseController", "open.211:" + clazz.getSimpleName());
            return;
        }
        LOG.d("BaseController", "open.214:" + clazz.getSimpleName());
        BaseActivity.open(this, clazz, pass);
    }

    public static <C extends BaseController> Bundle getFraArguments(Class<C> clazz,
                                                                    Serializable... pass) {
        Bundle bundle = new Bundle();
        if (pass != null) {
            LOG.d("BaseController", "getFraArguments.221:TAG_PASS");
            int index = -1;
            for (int i = 0; i < pass.length; i++) {
                if (pass[i] != null && pass[i].getClass().isArray()) {
                    Serializable[] obj = (Serializable[]) pass[i];
                    for (int i1 = 0; i1 < obj.length; i1++) {
                        if (index == -1) {
                            index = 0;
                        }
                        bundle.putSerializable(TAG_PASS + index, obj[index]);
                        index++;
                    }
                }
                if (index > 0) {
                    bundle.putSerializable(TAG_PASS + index, pass[i]);
                    index++;
                } else {
                    bundle.putSerializable(TAG_PASS + i, pass[i]);
                }
            }
            LOG.d("BaseActivity", "getFraArguments.TAG_PASS_DATA_SIZE:" + pass.length);
            bundle.putInt(TAG_PASS_DATA_SIZE, pass.length);
        }
        bundle.putSerializable(TAG_NAME, clazz);
        return bundle;
    }

    public int getActivityFlag() {
        return 0;
    }

    /**
     * 重新显示布局，常用于切换语言
     * 仅用于 Activity 模式
     */
    public final void clearView() {
        //    viewSparseArray.clear();
    }

    private BaseActivity mActivity;
    private BaseFragment mFragment;
    private PopupWindow mPopupWindow;
    private BaseController popController;
    private BaseController popParentController;
    private boolean isResume = true;
    private static long screenTime;
    long finishTime;
    boolean isFinish = false;

    protected BaseActivity getActivity() {
        if (mFragment != null) {
            return (BaseActivity) mFragment.getActivity();
        }
        return mActivity;
    }

    public void setActivity(BaseActivity pCommonActivity) {
        this.mActivity = pCommonActivity;
        this.mViewDelegate.setContext(pCommonActivity);
        this.mViewDelegate.setViewRoot(pCommonActivity);
    }

    public void setContext(BaseActivity pCommonActivity) {
        this.mActivity = pCommonActivity;
        this.mViewDelegate.setContext(pCommonActivity);
    }

    public void setViewRoot(View contentView) {
        this.mViewDelegate.setViewRoot(contentView);
    }

    public void setPopWindowParent(BaseController from) {
        this.popParentController = from;
    }

    public void setPopWindowControler(BaseController controller) {
        this.popController = controller;
    }

    public void setPopWindow(PopupWindow popupWindow) {
        this.mPopupWindow = popupWindow;
    }

    public void setFragment(BaseFragment fragment) {
        this.mFragment = fragment;
        this.mActivity = (BaseActivity) fragment.getActivity();
        this.mViewDelegate.setContext(fragment.getContext());
        this.mViewDelegate.setViewRoot(fragment);
        if (attach() != null) {
            CtrListener parent = CtrWatcher.get().findController(attach());
            if (parent instanceof BaseController) {
                ((BaseController) parent).addAttachItem(this);
                return;
            }
            Object parent2 = CtrWatcher2.get().findController(attach());
            if (parent2 instanceof BaseController) {
                ((BaseController) parent2).addAttachItem(this);
            }
        }
    }

    /**
     * 快速获取获取传递数据
     *
     * @param position <0  取到数位置 -1：最后一位。 -2：倒数第二位...
     * @see #finishOK(Serializable...)
     * {@link BaseActivity#getInnerIntent(BaseController, Class, Serializable...)}
     * {@link com.rq.base.ui.common.CommonFragment#instance(Class, Serializable...)}
     */
    public <T extends Serializable> T getPass(int position, Intent... pass) {
        int index;
        if (position < 0) {
            if (pass != null && pass.length > 0) {
                index = position + pass[0].getIntExtra(TAG_PASS_DATA_SIZE, 0);
            } else if (mFragment != null) {
                if (mFragment.getArguments() != null) {
                    index = position + mFragment.getArguments().getInt(TAG_PASS_DATA_SIZE, 0);
                } else {
                    index = position + mActivity.getIntent().getIntExtra(TAG_PASS_DATA_SIZE, 0);
                }
            } else {
                index = position + mActivity.getIntent().getIntExtra(TAG_PASS_DATA_SIZE, 0);
            }
        } else {
            index = position;
        }
        if (pass != null && pass.length > 0 && pass[0] != null) {
            return (T) pass[0].getSerializableExtra(TAG_PASS + index);
        }
        if (mFragment != null && mFragment.getArguments() != null) {
            return (T) mFragment.getArguments().getSerializable(TAG_PASS + index);
        }
        return (T) mActivity.getIntent().getSerializableExtra(TAG_PASS + index);
    }

    /**
     * @return 请求编码
     * {@link BaseActivity#openFor(BaseController, Class, Serializable...) getRequestCode()>0}
     * {@link BaseActivity#openWith(BaseController, int, Class, Serializable...) int --> getRequestCode()}
     * {@link BaseController#openFor(Class, Serializable...) getRequestCode()>0}
     * {@link BaseController#openWith(Class, int, Serializable...) int --> getRequestCode()}
     */
    public int getRequestCode() {
        if (mFragment != null) {
            int code = mFragment.getArguments().getInt(TAG_OPEN_CODE, 0);
            LOG.d("BaseController", "getRequestCode.Fra:" + code);
            return code;
        }
        int code = mActivity.getIntent().getIntExtra(TAG_OPEN_CODE, 0);
        LOG.d("BaseController", "getRequestCode:" + code);
        return code;
    }

    int getInnerPassCode() {
        LOG.d("BaseController", "getInnerPassCode:" + innerPassCode);
        if (getRequestCode() != 0) return getRequestCode();
        return innerPassCode;
    }

    void setInnerPassCode(int requestCode) {
        this.innerPassCode = requestCode;
        LOG.d("BaseController", "saveCode:" + requestCode);
    }

    protected void startActivityForResult(Intent intent) {
        setInnerPassCode((int) (System.currentTimeMillis() % (0xffff)));
        mActivity.startActivityForResult(intent, innerPassCode);
    }

    protected void startActivityForResult(Intent intent, int requestCode) {
        setInnerPassCode(requestCode);
        mActivity.startActivityForResult(intent, requestCode);
    }

    /**
     * @param code
     * @param data
     * @see #openWith(Class, int, Serializable...)
     */
    public final boolean isBackWith(int code, Intent data) {
        if (data != null) {
            int dataCode = data.getIntExtra("back.from.parent", Integer.MIN_VALUE);
            LOG.d("BaseController", "onResultOK.isBackWith>" + dataCode);
            return code == dataCode;
        }
        return false;
    }

    /**
     * @return true 已经处理逻辑  false 交给上层处理
     */
    final boolean onActivityResult(int requestCode, int resultCode, Intent data) {
        LOG.e("BaseController", this.getClass().getSimpleName() + ".onActivityResult:" + data);
        LOG.e("BaseController", "requestCode:" + requestCode);
        LOG.e("BaseController", "resultCode:" + resultCode);
        if (data == null) {
            data = new Intent();
        }
        if (getInnerPassCode() != 0) {
            data.putExtra("back.from.parent", getInnerPassCode());
        }
        if (onResult(requestCode, resultCode, data)) {
            return true;
        } else if (requestCode == getInnerPassCode() && resultCode == Activity.RESULT_OK) {
            if (onResultOK(data)) {
                return true;
            } else {
                return onResultOther(requestCode, resultCode, data);
            }
        }
        return onResultOther(requestCode, resultCode, data);
    }

    protected boolean onResult(int requestCode, int resultCode, Intent data) {
        return false;
    }

    public void onSaveInstanceState(Bundle outState) {
    }

    /**
     * Fragment 第一次展示
     */
    public void onFraFirstShow() {

    }

    //界面跳转操作者
    public interface Operator {

        void finish(BaseController controller);

        void finishOK(BaseController controller, Serializable... back);

        <P extends BaseController> boolean skip(BaseController controller, Class<P> clazz,
                                                Serializable... pass);

        <P extends BaseController> boolean open(BaseController controller, Class<P> clazz,
                                                Serializable... pass);

        <P extends BaseController> boolean openFor(BaseController controller, Class<P> clazz,
                                                   Serializable... pass);

        <P extends BaseController> boolean openWith(BaseController controller, Class<P> clazz, int requestCode,
                                                    Serializable... pass);
    }

    Operator mOperator;

    protected Operator getOperator() {
        return mOperator;
    }

    public void setOperator(Operator operator) {
        LOG.d("BaseController", this.getClass().getSimpleName() + ".setOperator.382:" + operator);
        this.mOperator = operator;
    }

    public void finish() {
        LOG.showUserWhere("BaseController_finish");
        if (System.currentTimeMillis() - finishTime < 200) {
            return;
        }
        this.isFinish = true;
        finishTime = System.currentTimeMillis();
        if (controllerFinish()) {
            return;
        }
        mActivity.setResult(Activity.RESULT_CANCELED);
        mActivity.finish();
    }

    private void finishFragment(Fragment fragment) {
        FragmentManager mFragmentManager = getActivity().getSupportFragmentManager();
        FragmentTransaction mTransaction = mFragmentManager.beginTransaction();
        mTransaction.hide(fragment);
        mTransaction.commitAllowingStateLoss();
    }

    public boolean controllerFinish(Serializable... pass) {
        if (mOperator != null) {

            LOG.d("BaseController", "controllerFinish.finish.FragmentContainer:" + mOperator);
            if (pass != null && pass.length > 0) {
                mOperator.finishOK(this, pass);
            } else {
                mOperator.finish(this);
            }
//            finishFragment(mFragment);
            mOperator = null;
            return true;
        }
        if (mPopupWindow != null) {
            LOG.d("BaseController", "controllerFinish.finish.392:" + mPopupWindow);
            mPopupWindow.dismiss();
            mPopupWindow = null;
            return true;
        }
        if (popParentController != null) {
            LOG.d("BaseController", "controllerFinish.finish.onActivityResult:");
            popParentController.onActivityResult(0, Activity.RESULT_CANCELED, null);
            mPopupWindow.dismiss();
            return true;
        }
        return false;
    }

    /**
     * 返回结果并且作为成功记过返回，调用<link>getPass(int,Intent)<link/>获取数据
     *
     * @param back
     * @see #getPass(int, Intent...)
     */
    public void finishOK(Serializable... back) {
        final Intent intent = new Intent();
        if (back != null) {
            LOG.d("BaseController", "finishOK.451:TAG_PASS");
            for (int i = 0; i < back.length; i++) {
                intent.putExtra(TAG_PASS + i, back[i]);
            }
            LOG.d("BaseController", "finishOK.TAG_PASS_DATA_SIZE:" + back.length);
            intent.putExtra(TAG_PASS_DATA_SIZE, back.length);
        }
        if (popParentController != null) {
            LOG.d("BaseController", "finishOK.onActivityResult:");
            popParentController.onActivityResult(getInnerPassCode(), Activity.RESULT_OK, intent);
            mPopupWindow.dismiss();
            this.finish();
            return;
        }
        if (controllerFinish(back)) {
            return;
        }
        mActivity.setResult(Activity.RESULT_OK, intent);
        mActivity.finish();
    }

    public void finish(int resultCode, Serializable... back) {
        Intent intent = new Intent();
        if (back != null) {
            LOG.d("BaseController", "finish.470:TAG_PASS");
            for (int i = 0; i < back.length; i++) {
                intent.putExtra(TAG_PASS + i, back[i]);
            }
            LOG.d("BaseController", "finish.TAG_PASS_DATA_SIZE:" + back.length);
            intent.putExtra(TAG_PASS_DATA_SIZE, back.length);
        }
        this.isFinish = true;
        mActivity.setResult(resultCode, intent);
        mActivity.finish();
    }

    protected boolean onResultOK(Intent data) {
        return false;
    }

    protected boolean onResultOther(int requestCode, int resultCode, @Nullable Intent data) {
        LOG.d("BaseController", "onResultOther.231:");
        return false;
    }

    private final boolean hasOverride() {

        try {
            this.getClass().getDeclaredMethod("isStatusBarTextDark", null);
            return true;
        } catch (NoSuchMethodException e) {
        }
        try {
            this.getClass().getDeclaredMethod("statusBarBackgroundColor", null);
            return true;
        } catch (NoSuchMethodException e) {
        }
        return false;
    }


    public void onViewCreated(Bundle savedInstanceState) {
        LOG.e("BaseController", "600:");
        this.mViewDelegate.initController(this);
        this.mViewDelegate.onViewCreate(savedInstanceState);
        initWatcher();
        if (!showStatusBar()) {
            LOG.e("BaseController", "588:ImmersionBar");
            ImmersionBar.with(getActivity()).init();
        } else if (underStatusBar()) {
            LOG.e("BaseController", "591:ImmersionBar");
            ImmersionBar.with(getContext()).statusBarDarkFont(isStatusBarTextDark(), isStatusBarTextDark() ? 0F : 1F).statusBarColor(statusBarBackgroundColor()).init();
        } else if (hasOverride()) {
            LOG.e("BaseController", "594:ImmersionBar");
            ImmersionBar.with(getActivity()).fitsSystemWindows(true).statusBarDarkFont(isStatusBarTextDark(), isStatusBarTextDark() ? 0F : 1F).statusBarColor(statusBarBackgroundColor()).init();
        } else {
            LOG.e("BaseController", "614:ImmersionBar");
        }
    }

    private void initWatcher() {
        long startTime = System.currentTimeMillis();
        if (isImplements(CtrListener.class)) {
            Method method = null;
            try {
                method = get(CtrListener.class).getClass().getMethod("tagInfo", String.class, Object[].class);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            if (method != null) {
                Annotation[] annotations = method.getAnnotations();
                if (annotations.length > 0) {
                    for (Annotation annotation : annotations) {
                        if (annotation instanceof CtrTag) {
                            CtrTag inject = (CtrTag) annotation;
                            String[] ids = inject.value();
                            for (String tag : ids) {
                                CtrWatcher.get().watch(tag, (CtrListener) this);
                            }
                            LOG.e("BaseController", "initWatcher 方法一耗时<加载>:" + (System.currentTimeMillis() - startTime));
                            return;
                        }
                    }
                }
            }
        }
        Method[] methods = this.getClass().getMethods();
        for (Method method : methods) {
            Annotation[] annotations = method.getAnnotations();
            if (annotations.length > 0) {
                for (Annotation annotation : annotations) {
                    if (annotation instanceof CtrTag) {
                        CtrTag inject = (CtrTag) annotation;
                        String[] ids = inject.value();
                        for (String tag : ids) {
                            CtrWatcher2.get().watch(tag, this);
                        }
                        LOG.e("BaseController", "initWatcher 方法二耗时<加载>:" + (System.currentTimeMillis() - startTime));
                    }
                }
            }
        }
        LOG.e("BaseController", "initWatcher 耗时<未加载>:" + (System.currentTimeMillis() - startTime));
    }


//  private void initRefuse() {
//    if (isImplements(OnRefuseAndLoadListener.class)) {
//      Method method = null;
//      try {
//        method = get(OnRefuseAndLoadListener.class).getClass().getDeclaredMethod("refuse", int.class);
//      } catch (NoSuchMethodException e) {
//        e.printStackTrace();
//      }
//      if (method != null) {
//        Annotation[] annotations = method.getAnnotations();
//        if (annotations.length > 0) {
//          for (Annotation annotation : annotations) {
//            if (annotation instanceof OnRefuseAndLoad) {
//              OnRefuseAndLoad inject = (OnRefuseAndLoad) annotation;
//              int id = inject.viewId();
//              if (id > 0) {
//                setOnRefuseAndLoadListener(id, get(OnRefuseAndLoadListener.class), inject
//                        .loadAble(), inject.refuseAble());
//              }
//            }
//          }
//          get(OnRefuseAndLoadListener.class).refuse(BASE.PAGE_SIZE_START);
//        }
//      }
//    }
//  }

    /**
     * 隐藏标题栏
     */
    protected final void hideTitle() {
        setData2View(R.id.common_title_pan, View.GONE);
    }

    protected final boolean isImplements(Class<?> clazz) {
        return clazz.isAssignableFrom(this.getClass());
    }

    public <T> T get(Class<T> type) {
        return type.cast(this);
    }

    public final void runOnUiThread(Runnable action) {
        mActivity.runOnUiThread(action);
    }

    final Handler mHandler = new Handler(Looper.getMainLooper());

    public final void runOnUiThread(Runnable action, long delayMillis) {
        mHandler.postDelayed(action, delayMillis);
    }

    protected void initTitle(int title) {
        initTitle(getString(title));
    }

    protected void initTitle(String title) {
        initTitle(title, 0);
    }

    protected void initTitle(String title, int clickImg) {
        setData2View(R.id.common_title, title);
        if (clickImg > 0) {
            setData2View(R.id.common_right_click, clickImg);
            setOnClickListener(v -> rightClick(v), R.id.common_right_click);
        } else {
            setData2View(R.id.common_right_click, View.GONE);
        }
        setOnClickListener(v -> finish(), R.id.common_left_back);
    }

    protected void initTitle(String title, String clickBtn) {
        setData2View(R.id.common_title, title);
        setData2View(R.id.common_right_click_txt, clickBtn);
        if (!TextUtils.isEmpty(clickBtn)) {
            setData2View(R.id.common_right_click_txt, View.VISIBLE);
            setOnClickListener(v -> rightClick(v), R.id.common_right_click_txt);
        }
        setOnClickListener(v -> finish(), R.id.common_left_back);
    }

    protected void rightClick(View v) {
    }

    /**
     * 无视调用线程,自动识别视图和数据进行相应填充,包含以下规则
     * <p>
     * viewId   ->  所有
     * obj ->  {@value android.view.View#VISIBLE 等}        == setVisibility
     * {@link com.rq.base.ui.impl.ViewParam}       见该类描述
     * View.OnClickListener                        ==  setOnClickListener
     * {@link Boolean}     CompoundButton.setChecked       Other.setSelected
     * <p>
     * viewId   ->  TextView
     * obj      ->  CharSequence    ==  setText(obj)
     * ->  null            ==  setText("")
     * ->  int             ==  setText(getContext().getResources().getText(obj));
     * ->  others          ==  setText(String.valueOf(obg))
     * <p>
     * viewId   ->  ImageView
     * obj  ->  {@link android.graphics.Bitmap}             ==  setImageBitmap((Bitmap) obj)
     * ->  {@link android.graphics.drawable.Drawable}  ==  setImageDrawable((Drawable) obj)
     * ->  {@link Integer}                             ==  setImageResource((int) obj)
     * ->  {@link java.net.URL}                        ==  ImageLoadUtil.display(getContext(), obj, view)
     * ->  String("http...")                           ==  ImageLoadUtil.display(getContext(), obj, view)
     * ->  String("#...")                              ==  setBackgroundColor(Color.parseColor(con))
     * <p>
     * viewId   ->  RecyclerView
     * obj ->  {@link com.rq.rvlibrary.RecyclerUtil}
     * {@link android.widget.BaseAdapter}
     *
     * @param viewId
     * @param obj
     */
    public synchronized void setData2View(final int viewId, final Object obj) {
        this.mViewDelegate.setData2View(viewId, obj);
    }

    public synchronized void setData2View(final int viewId, final Object... obj) {
        this.mViewDelegate.setData2View(viewId, obj);
    }

    public synchronized void setViewTag(final int viewId, final Object tag) {
        this.mViewDelegate.setViewTag(viewId, tag);
    }

    public void setData2View(final View viewId, final Object obj) {
        this.mViewDelegate.setDataToView(viewId, obj);
    }

    /**
     * {@link Activity#onBackPressed()}
     */
    public boolean interruptBack() {
        return false;
    }

    public void setOnClickListener(View.OnClickListener listener, int... ids) {
        if (ids == null || ids.length == 0 || listener == null) {
            return;
        }
        for (int id : ids) {
            View view = getView(id);
            if (view != null) {
                view.setOnClickListener(listener);
            }
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return false;
    }

    public String getInput(int viewId) {
        return mViewDelegate.getInput(viewId, 0);
    }

//    public String getSpinner(int viewId, String... value) {
//        return mViewDelegate.getSpinner(viewId, value);
//    }

    public String getInput(int viewId, int sub) {
        return mViewDelegate.getInput(viewId, sub);
    }

    public Object getViewTag(int viewId) {
        return mViewDelegate.getViewTag(viewId);
    }

    /**
     * 为了简化逻辑 ，会在设置View的时候加载一次 refuse(1)
     * RefreshAble 默认 true
     * <p>
     * Object... boolean + boolean >>LoadAble + RefreshAble
     * null 根据 SmartRefreshLayout父布局 外层高度 与 SmartRefreshLayout 高度自行设置 LoadAble
     * <p>
     * api  'io.github.scwang90:refresh-layout-kernel:2.0.5'      //核心必须依赖
     * api  'io.github.scwang90:refresh-header-classics:2.0.5'    //经典刷新头
     * api  'io.github.scwang90:refresh-footer-classics:2.0.5'    //经典加载
     * <p>
     */
    public void setOnRefuseAndLoadListener(int viewId, final OnRefuseAndLoadListener listener,
                                           Object... refuseAndLoad) {
//        this.refuseViewId = viewId;
//        final SmartRefreshLayout refreshLayout = getView(viewId);
//        if (refreshLayout == null || listener == null) return;
//        refreshLayout.setRefreshHeader(new ClassicsHeader(getContext()));
//        refreshLayout.setRefreshFooter(new ClassicsFooter(getContext()));
//        refreshLayout.setTag(R.id.tag_refuse_page, BASE.PAGE_SIZE_START);
//        listener.refuse(BASE.PAGE_SIZE_START);
//        refreshLayout.setOnRefreshListener(new OnRefreshListener() {
//            @Override
//            public void onRefresh(@NonNull RefreshLayout refreshLayoutImpl) {
//                refreshLayout.setTag(R.id.tag_refuse_page, BASE.PAGE_SIZE_START);
//                listener.refuse(BASE.PAGE_SIZE_START);
//            }
//
//        });
//        refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() {
//            @Override
//            public void onLoadMore(@NonNull RefreshLayout refreshLayoutImpl) {
//                int page = (int) refreshLayout.getTag(R.id.tag_refuse_page);
//                page++;
//                refreshLayout.setTag(R.id.tag_refuse_page, page);
//                listener.refuse(page);
//            }
//        });
//        if (refuseAndLoad.length > 0) {
//            if (refuseAndLoad[0] instanceof Boolean) {
//                refreshLayout.setEnableLoadMore((Boolean) refuseAndLoad[0]);
//            } else {
//                refreshLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
//                    @Override
//                    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
//                                               int oldTop, int oldRight, int oldBottom) {
//                        refreshLayout
//                                .setEnableLoadMore(v.getHeight() >= ((View) v.getParent().getParent()).getHeight());
//                    }
//                });
//            }
//        }
//        if (refuseAndLoad.length > 1) {
//            if (refuseAndLoad[1] instanceof Boolean) {
//                refreshLayout.setEnableRefresh((Boolean) refuseAndLoad[1]);
//            }
//        }
    }

    protected final void setRefuseAndLoad(boolean refuse, boolean load) {
//        final SmartRefreshLayout refreshLayout = getView(refuseViewId);
//        if (refreshLayout == null) return;
//        refreshLayout.setEnableRefresh(refuse);
//        refreshLayout.setEnableLoadMore(load);
    }

    protected void refuseLoadAble(List data) {
        if (data != null && data.size() == RequestType.PAGE_SIZE) {
            setRefuseAndLoad(true, true);
        } else {
            setRefuseAndLoad(true, false);
        }

    }

    public void finshRAL() {
        if (refuseViewId == 0) return;
//        final SmartRefreshLayout refreshLayout = getView(refuseViewId);
//        if (refreshLayout == null) return;
//        refreshLayout.finishRefresh();
//        refreshLayout.finishLoadMore();
    }

    public <T extends View> T getView(int id) {
        return this.mViewDelegate.getView(id);
    }

    protected Class<?> attach() {
        return null;
    }

    public List<BaseController> getAttachChild() {
        return attachChild;
    }

    void addAttachItem(BaseController item) {
        attachChild.add(item);
    }

    public boolean dettachItem(BaseController item) {
        return attachChild.remove(item);
    }

    public final void onControllerResume() {
        // TODO: 2022/12/1 回调异常， 配合FragmentSaveTabHost 有重复回调    onResume
        onResume();
        if (getAttachChild().size() > 0) {
            LOG.d("BaseController", this.getClass()
                    .getSimpleName() + ".onControllerResume.925:" + getAttachChild()
                    .size());
            for (BaseController item : getAttachChild()) {
                item.onResume();
            }
        }
    }

    public final void onControllerPause() {
        onPause();
        if (getAttachChild().size() > 0) {
            for (BaseController item : getAttachChild()) {
                item.onPause();
            }
        }
    }

    public void onActivityResume() {
    }

    public void onActivityPause() {
    }

    public void onActivityDestroy() {
        this.isFinish = true;
        mHandler.removeCallbacksAndMessages(null);
    }


    public final Object reflect(String methodName, Class clazz, Object... param) {
        Object body = null;
        if (clazz.isInstance(mActivity)) {
            body = mActivity;
        } else if (clazz.isInstance(mFragment)) {
            body = mFragment;
        } else {
            LOG.e("BaseController", "974:error:" + (clazz != null ? clazz.getSimpleName() + " don't support reflect" : "clzz is null"));
            return null;
        }
        return reflectObject(methodName, body, clazz, param);
    }

    public final Object reflectActivity(String methodName, Object... param) {
        return reflectObject(methodName, mActivity, Activity.class, param);
    }

    public final Object reflectFragment(String methodName, Object... param) {
        return reflectObject(methodName, mFragment, Fragment.class, param);
    }

    private Object reflectObject(String methodName, Object body, Class c1, Object... param) {
        Class[] claParams = new Class[param.length];
        if (param.length > 0) {
            for (int i = 0; i < param.length; i++) {
                claParams[i] = param[i].getClass();
            }
        }
        try {
            Method setMethod = c1.getMethod(methodName, claParams);
            return setMethod.invoke(body, param);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public boolean isResume() {
        return isResume;
    }

    protected void onPause() {

        this.isResume = false;
        screenTime = System.currentTimeMillis();
        LOG.d("BaseController", "    onPause  ->  " + getClass().getSimpleName());
    }

    protected void onResume() {
        this.isResume = true;
        LOG.showUserWhere("onResume", 12);
        LOG.d("BaseController", "    onResume  ->  " + getClass().getSimpleName());
        LOG.d("BaseController", "    getRequestCode  ->  " + getRequestCode());
    }

    @LayoutRes
    public abstract int getLayoutId();

    protected final synchronized void setDataToView(View view, Object obj) {
        this.mViewDelegate.setDataToView(view, obj);
    }

    @Override
    public <T> void handleFailResponse(T baseBean) {
        if (popController != null) {
            popController.handleFailResponse(baseBean);
        } else if (mFragment != null) {
            mFragment.handleFailResponse(baseBean);
        } else {
            mActivity.handleFailResponse(baseBean);
        }
        finshRAL();
    }

    public boolean isShowProgress() {
        return popParentController != null && popParentController
                .isShow() || mFragment != null && mFragment
                .isShowProgress() || mActivity != null && mActivity.isShowProgress();
    }

    @Override
    public void showLoading(String... msg) {
        LOG.showLongWhere("showLoading");
        if (popParentController != null) {
            popParentController.showLoading(msg);
            LOG.d("BaseController", "showLoading.1244:");
            return;
        }
        if (mFragment != null) {
            LOG.d("BaseController", "showLoading.1248:");
            mFragment.showLoading(msg);
        } else {
            LOG.d("BaseController", "showLoading.1251:");
            mActivity.showLoading(msg);
        }
    }


    @Override
    public void dismissLoading() {
        LOG.d("BaseController", "dismissLoading.showLoading:");
        if (popParentController != null) {
            popParentController.dismissLoading();
            return;
        }
        //    finshRAL();
        if (mFragment != null) {
            mFragment.dismissLoading();
        } else {
            mActivity.dismissLoading();
        }
    }

    @Override
    public Activity getContext() {
        if (mFragment != null) {
            return mFragment.getActivity();
        }
        return getActivity();
    }

    //  @Override
    //  public <T> LifecycleTransformer<T> bindToLifecycle() {
    //    if (popParentController != null) {
    //      return popParentController.bindToLifecycle();
    //    } else if (mFragment != null) {
    //      return mFragment.bindToLifecycle();
    //    } else if (mActivity != null) {
    //      return mActivity.bindToLifecycle();
    //    } else if (popParentController != null) {
    //      return popParentController.bindToLifecycle();
    //    }
    //    return null;
    //  }

    @Override
    public <T> void onResponseSucceed(@NonNull RequestType type, T data) {
        finshRAL();
//        if (data != null) {
//            DialogHelper.showRemind(getContext(),type.toString()+"\n"+ GsonUtil.getString(data), null);
//        }
        if (popController != null) {
            popController.onResponseSucceed(type, data);
        } else if (mFragment != null) {
            mFragment.onResponseSucceed(type, data);
        } else if (mActivity != null) {
            mActivity.onResponseSucceed(type, data);
        } else if (popParentController != null) {
            popParentController.onResponseSucceed(type, data);
        } else {
//            LOG.d("BaseController", this.getClass().getSimpleName() + ".onResponseSucceed.1271:" + type
//                    .getType());
        }
    }


    @Override
    public <T> void onResponseError(@NonNull RequestType type, T data) {
        LOG.e("BaseController", "onResponseError.1025:" + type.getErrorMsg());
        LOG.e("BaseController", "onResponseError.1026:" + data.getClass().getSimpleName());
        LOG.e("BaseController", "onResponseError.1027:" + data);
        finshRAL();
        dismissLoading();
        if (data instanceof BaseBeanImpl) {
            if (((BaseBeanImpl) data).getCode() == 402) {
                ToastUtil.show("账号已在其他地方登录，请重新登录系统");
                skip(BASE.getLoginHelper());
            } else {
                ToastUtil.show(((BaseBeanImpl) data).getRespMsg());
            }
            //    } else {
            //      HttpParamUtil.commonError(this, type);
        } else if (data instanceof String) {
            ToastUtil.show((String) data);
        } else {
            ToastUtil.show(type.getErrorMsg());
        }
        if (popController != null) {
            popController.onResponseError(type, data);
        } else if (mFragment != null) {
            if (mFragment != null) {
                mFragment.onResponseError(type, data);
            }
        } else {
            if (mActivity != null) {
                mActivity.onResponseError(type, data);
            }
        }
    }

    @Override
    public void onConnectError(@NonNull RequestType type) {
        dismissLoading();
        //    if (NetWorkMonitorManager.getInstance().isNetOk()) {
        //      LOG.d("BaseController", type.getType() + ".onConnectError.数据获取异常>>" + type.getErrorMsg());
        //    } else {
        //      LOG.d("BaseController", type.getType() + ".onConnectError.网络异常>>" + type.getErrorMsg());
        //    }
    }

    public void startActivity(Intent intent) {//兼容写法
        mActivity.startActivity(intent);
    }

    /**
     * 适用于 跳转特殊ACT的回参获取
     */
    @Deprecated
    protected Intent getIntent() {
        return mActivity.getIntent();
    }

    public String getString(int strRes) {
        if (mActivity == null) {
            return "";
        }
        return mActivity.getString(strRes);
    }


    protected boolean isShow() {
        if (getActivity() == null) {
            return false;
        }
        if (mFragment == null && AppUtils.isForeground(getActivity())) {
            return true;
        }
        if (mFragment != null) {
            return mFragment.isResumed();
        }
        return false;
    }

    /**
     * @deprecated scrollY 计算方式不科学，只适用于单一子项的RV
     */
    public boolean recyclerToTop(final int hideViewId, int listId) {
        if (getView(hideViewId) == null || getView(listId) == null) {
            return false;
        }
        if (getView(listId) instanceof RecyclerView) {
            ((RecyclerView) getView(listId)).addOnScrollListener(new RecyclerView.OnScrollListener() {
                int scrollY = 0;

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    int targetHeight = getView(hideViewId).getMeasuredHeight();
                    scrollY += dy;
                    setData2View(hideViewId, Math.abs(scrollY) > targetHeight ? View.GONE : View.VISIBLE);
                    LOG.d("BaseController", scrollY + ".757:" + targetHeight);
                }
            });
            return true;
        }
        //        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        //            getView(listId).setOnScrollChangeListener(new View.OnScrollChangeListener() {
        //                @Override
        //                public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
        //                    int targetHeight = getView(hideViewId).getHeight();
        //                    setData2View(hideViewId, scrollY > targetHeight ? View.GONE : View.VISIBLE);
        //                    LOG.d("BaseController", scrollY + ".768:" + targetHeight);
        //                }
        //            });
        //            return true;
        //        }
        return false;
    }

    /**
     * @return 是否补足 状态栏 空白视图
     */
    public boolean justLayout() {
        return false;
    }

//    public boolean blackStatusText() {
//        return false;
//    }

    public boolean needTitleSpace() {
        return false;
    }

    /**
     * @return false -> 不显示状态栏,默认展示
     */
    public boolean showStatusBar() {
        return true;
    }

    public boolean isStatusBarTextDark() {
        return true;
    }

    @ColorRes
    protected int statusBarBackgroundColor() {
        if (underStatusBar()) {
            return R.color.transparent;
        }
        return isStatusBarTextDark() ? R.color.white : android.R.color.black;
    }

    /**
     * @return 是否布局到正常状态栏位置 true 布局会上提 不会加载 statusBarBackgroundColor()方法
     */
    public boolean underStatusBar() {
        return false;
    }

    /**
     * @return true 弹窗风格,背景带透明度
     */
    public boolean isTranslucent() {
        return false;
    }

    /**
     * @return 是否展示 common_status_bar 布局
     */
    public boolean needTitle() {
        return true;
    }


    /**
     * @return 界面是否自动拉长可滑动(外层自动填充ScrollView / NestedScrollView)
     */
    public boolean needOutScroll() {
        return true;
    }

//    此方法暂未确定添加原因 保留代码 @BaseActivity.initView
//    public void refuseStatusBar() {
//        refuseStatusBar(blackStatusText());
//    }
//
//    public void refuseStatusBar(boolean isDarkText) {
//        if (underStatusBar()) {
//            LOG.d("BaseController", this.getClass()
//                    .getSimpleName() + ".refuseStatusBar:1003 ImmersionBar = " + isDarkText);
//            ImmersionBar.with(getContext()).statusBarColor(R.color.transparent).init();
//        } else if (getView(R.id.common_status_bar) == null) {
//            LOG.d("BaseController", this.getClass()
//                    .getSimpleName() + ".refuseStatusBar:1006 ImmersionBar = " + isDarkText);
//            ImmersionBar.with(getContext()).statusBarDarkFont(isDarkText).fitsSystemWindows(true)
//                    .statusBarColor(R.color.status_bg_color).fullScreen(true).init();
//        } else {
//            LOG.d("BaseController", this.getClass()
//                    .getSimpleName() + ".refuseStatusBar:1009 ImmersionBar = " + isDarkText);
//            ImmersionBar.with(getContext()).statusBarDarkFont(isDarkText).init();
//        }
//    }

    public View inflateRootView(LayoutInflater inflater) {
        View root = inflateRootView(inflater, false);
        return root;
    }

    public View inflateRootView(LayoutInflater inflater, boolean isFragment) {
        int layout = getLayoutId();
        if (layout == 0) {
            return null;
        }
        View root;
        if (justLayout()) {
            root = inflater.inflate(layout, null);
        } else if (needOutScroll()) {
            final View content = inflater.inflate(layout, null);
            int hasScrollView = checkHasScroller(content);
            root = inflater.inflate(BASE.getLayoutId(hasScrollView, isFragment), null);
            final ViewGroup container = root.findViewById(R.id.base_container);
            container.getViewTreeObserver()
                    .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                        @Override
                        public void onGlobalLayout() {
                            int height = ((View) container.getParent()).getHeight();
                            int height2 = container.getHeight();
                            if (height2 < height && height2 != 0) {
                                ViewGroup.LayoutParams param1 = container.getLayoutParams();
                                param1.height = height;
                                container.setLayoutParams(param1);

                                ViewGroup.LayoutParams param2 = content.getLayoutParams();
                                param2.height = height;
                                content.setLayoutParams(param2);
                            }
                            container.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        }
                    });

            container.addView(content, MATCH_PARENT, MATCH_PARENT);
        } else {
            root = inflater
                    .inflate(isFragment ? R.layout.fragment_base_no_scroller : R.layout.activity_base_no_scroller, null);
            final ViewGroup container = root.findViewById(R.id.base_container);
            final View content = inflater.inflate(layout, null);
            container.addView(content);
        }
        if (needTitleSpace() && root.findViewById(R.id.title_space) != null) {
            root.findViewById(R.id.title_space).setVisibility(View.VISIBLE);
        }
        if (!showStatusBar() && root.findViewById(R.id.common_status_bar) != null) {
            root.findViewById(R.id.common_status_bar).setVisibility(View.GONE);
        }
        if (root.findViewById(R.id.common_title_pan) != null) {
            root.findViewById(R.id.common_title_pan)
                    .setVisibility(needTitle() ? View.VISIBLE : View.GONE);
        }

        return root;
    }

    protected int checkHasScroller(View content) {
        int hasSC = 0;
        if (content instanceof ViewGroup) {
            hasSC = checkParentHasScrollView((ViewGroup) content);
        }
        LOG.d("BaseActivity", "checkHasScroller:" + hasSC);
        return hasSC;
    }

    private int checkParentHasScrollView(View view) {
        if (null == view) {
            return 0;
        }
        if (view instanceof ViewGroup) {
            //遍历ViewGroup,是子view加1，是ViewGroup递归调用
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                View child = ((ViewGroup) view).getChildAt(i);
                if (child instanceof ViewGroup) {
                    if (child instanceof ScrollView || child instanceof RecyclerView) {
                        return 1;
                    }
//                    if (child instanceof SmartRefreshLayout) {//SmartRefreshLayout 与 外部滑动冲突
//                        return 2;
//                    }
                    if (checkParentHasScrollView(((ViewGroup) view).getChildAt(i)) == 1) {
                        return 1;
                    } else if (checkParentHasScrollView(((ViewGroup) view).getChildAt(i)) == 2) {
                        return 2;
                    }
                }
            }
        }
        return 0;
    }


    public void onFragmentDetach() {
        boolean detach = attachChild.remove(this);
        this.mFragment = null;
        LOG.d("BaseController", "onFragmentDetach.1373:" + detach);
    }

    public float getDimension(int id) {//缓解部分情况出现 getConetxt 为空的情况
        if (id != 0 && getContext() != null) {
            return getContext().getResources().getDimension(id);
            //    } else {
            //      BuglyLog.d("BaseController", "getDimension getDimension -> getContext == null");
        }
        return 0;
    }

}
